package testing;

import junit.framework.Assert;

import org.junit.Test;

import com.numericalmethod.algoquant.model.ralph2009.draft.AbstractFunction;
import com.numericalmethod.algoquant.model.ralph2009.draft.SystemOfEquationsSolver;

public class SystemOfEquationsSolverTest {

	
	@Test
	public void testSingleEquation() {
		

		AbstractFunction f=new AbstractFunction() {
			public int getAxisCount() {
				return 1;
			}
			
			public double compute(double[] input) {			
				return Math.pow(Math.exp(input[0]*input[0]+2*Math.exp(input[0]))-2.0, 2.0)-80;
			}
		};
		
		SystemOfEquationsSolver s=new SystemOfEquationsSolver();
		s.addEquation(f);
		
		double epsilon=0.0000000000001;
		double[] solution=s.solve(new double[] { -0.3 }, 1000000, epsilon);
		
		System.out.println("testSingleEquation: solution="+solution[0]);
		
		double functionOutput = f.compute(solution);
		Assert.assertEquals(0.0, functionOutput, 0.0000001);
		
	}
	
	
	@Test
	public void testMultipleEquationsCase1() {
		AbstractFunction func1=new AbstractFunction() {
			public int getAxisCount() {
				return 3;
			}
			
			public double compute(double[] input) {			
				double x=input[0];
				double y=input[1];
				double z=input[2];
				return Math.exp(-2.0*x*x*x)+4.0*y*y+z-1.0;
			}
		};
		
		AbstractFunction func2=new AbstractFunction() {
			public int getAxisCount() {
				return 3;
			}
			
			public double compute(double[] input) {
				double x=input[0];
				double y=input[1];
				double z=input[2];
				return z*Math.cos(18.0*y-14.0*x*x);
			}
		};
		
		AbstractFunction func3=new AbstractFunction() {
			public int getAxisCount() {
				return 3;
			}
			public double compute(double[] input) {
				double x=input[0];
				double y=input[1];
				double z=input[2];
				return x*y-10.0*z*y*y;
			}
		};
		
		SystemOfEquationsSolver s=new SystemOfEquationsSolver();
		s.addEquation(func1);
		s.addEquation(func2);
		s.addEquation(func3);
		double epsilon= 0.0000000000001;
		double[] solution=s.solve(new double[] { 0.3, -4.0, 0.9 }, 1000000,epsilon);
		
		System.out.println("testMultipleEquationsCase1: solution= "+solution[0]+", "+solution[1]+", "+solution[2]);
		double output1 = func1.compute(solution);
		double output2 = func2.compute(solution);
		double output3 = func3.compute(solution);
		Assert.assertEquals(0.0, output1, 0.0000001);
		Assert.assertEquals(0.0, output2, 0.0000001);
		Assert.assertEquals(0.0, output3, 0.0000001);
		
	}
	
}
